package com.ec.edu.common.hello;

import com.alibaba.fastjson.JSON;
import com.ec.edu.common.enums.MsgType;
import com.ec.edu.common.constants.NettyConstant;
import com.ec.edu.common.constants.NettyMap;
import com.ec.edu.common.enums.RoomType;
import com.ec.edu.common.hello.send.MsgSendService;
import com.ec.edu.common.hello.send.impl.NormalMsgSendService;
import com.ec.edu.common.vo.*;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

@Slf4j
@ChannelHandler.Sharable
public class ClientHandler extends SimpleChannelInboundHandler<Object> {

    ChannelHandlerContext ctx;
    private int pingTime = 0;//心跳次数
    MessageVo heartBeatMsg = null;//心跳数据
    String clientId="";

    public ClientHandler(String clientId) {
        this.clientId=clientId;
        DeviceHeartBeatVo heartBeat = new DeviceHeartBeatVo();
        heartBeat.setTimeSp(System.currentTimeMillis());
        heartBeatMsg = new MessageVo(0, clientId, heartBeat);
    }

    /**
     * 利用写空闲发送心跳检测消息
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            switch (e.state()) {
                case WRITER_IDLE:
                    //发送心跳到服务器
                    //一分钟发送一次心跳
                    pingTime++;

                    //一天重置一次
                    if(pingTime == 1024){
                        pingTime = 0;
                    }
                    ctx.writeAndFlush(heartBeatMsg);
                    log.info("客户端发送心跳----------");
                    break;
                default:
                    break;
            }
        }
//        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        NettyConstant.CLIENT_NETWORK_STATUS=1;
        System.out.println("tcp链路建立成功后调用");
        this.ctx = ctx;

        MessageVo messageVo = new MessageVo();
        messageVo.setMsgType(MsgType.DEVICE.getMsgType());
        messageVo.setClientId(clientId);
        DeviceParamsVo deviceParamsVo = new DeviceParamsVo();
        deviceParamsVo.setSimIccid("1233456678789");
        messageVo.setRemark("Are you ok?");
        messageVo.setData(deviceParamsVo);

        ctx.channel().writeAndFlush(messageVo);

        Channel channel = ctx.channel();
        NettyMap.channelMap.put(clientId, channel.id());
        NettyMap.channels.add(channel);
        //发送登录消息
        ctx.fireChannelActive();

//        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        NettyConstant.CLIENT_NETWORK_STATUS=0;
        Channel channel = ctx.channel();
        NettyMap.channelMap.remove(clientId);
        NettyMap.channels.remove(channel);
        log.info("-------客户端下线----------");

        //1、断线重连
        //断线时，触发channelInactive方法，然后调用run()方法实现重连；
        //2、client启动连接服务器时，连接失败，调用run()方法实现重连；
        //run()：重连，如果没有连上服务端，则触发channelInactive方法，再次循环调用run()；如果连接上，则触发channelActive方法，把clientId和socketChannel存储起来

//        super.channelInactive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        //获取当前channel
        this.ctx = ctx;
        log.info("channelRead0:{}", JSON.toJSONString(msg));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("异常：", cause);
        ctx.close();
//        super.exceptionCaught(ctx, cause);
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("助手类添加");
        NettyMap.channels.add(ctx.channel());
        super.handlerAdded(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("助手类移除");
        NettyMap.channels.remove(ctx.channel());
        super.handlerRemoved(ctx);
    }

    public boolean sendMsg(String msg) {
        MessageVo messageVo = new MessageVo();
        messageVo.setMsgType(MsgType.TEXT.getMsgType());
        messageVo.setRoomType(RoomType.ONE_TO_ONE.getRoomType());
        messageVo.setClientId(clientId);
        messageVo.setRemark(msg);
        ChatTextParamsVo chatTextParamsVo = new ChatTextParamsVo();

        //TODO 临时方案，手工指定发送人
        if (msg.contains(":")) {
            String[] split = msg.split(":");
            if (split.length > 1) {
                messageVo.setToClientId(split[1]);
            }
        }
        chatTextParamsVo.setChatText(msg);
        messageVo.setData(chatTextParamsVo);

        sendMsg(messageVo);

        return msg.equals("q") ? false : true;
    }

    public void sendMsg(MessageVo messageVo) {
        if(StringUtils.isEmpty(messageVo.getMsgType())){
            log.error("消息类型不能为空");
        } else {
            MsgSendService msgSendService = new NormalMsgSendService();
            msgSendService.send(messageVo);
        }
    }
}
